"""
AI报告生成器核心模块

提供报告生成的基础架构和抽象接口，定义标准的报告生成流程。
遵循模板方法模式，确保所有报告类型都有一致的生成流程。
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Dict, Any, Optional
import pandas as pd
from datetime import datetime
import logging

logger = logging.getLogger(__name__)


@dataclass
class RawData:
    """原始数据容器"""
    base_data: Optional[pd.DataFrame] = None
    work_data: Optional[pd.DataFrame] = None
    equipment_data: Optional[pd.DataFrame] = None
    metadata: Dict[str, Any] = None
    
    def __post_init__(self):
        if self.metadata is None:
            self.metadata = {}


@dataclass
class ProcessedData:
    """处理后的数据容器"""
    statistics: Dict[str, Any]
    dataframes: Dict[str, pd.DataFrame]
    metrics: Dict[str, float]
    metadata: Dict[str, Any]
    
    def __post_init__(self):
        if self.statistics is None:
            self.statistics = {}
        if self.dataframes is None:
            self.dataframes = {}
        if self.metrics is None:
            self.metrics = {}
        if self.metadata is None:
            self.metadata = {}


@dataclass
class ReportResult:
    """报告生成结果"""
    success: bool
    url: Optional[str] = None
    content: Optional[str] = None
    error_message: Optional[str] = None
    metadata: Dict[str, Any] = None
    
    def __post_init__(self):
        if self.metadata is None:
            self.metadata = {}


class BaseReportGenerator(ABC):
    """
    报告生成器抽象基类
    
    定义了报告生成的标准流程：数据提取 -> 数据转换 -> AI分析 -> 输出生成
    子类需要实现具体的业务逻辑，但遵循统一的处理流程。
    """
    
    def __init__(self, config: Dict[str, Any]):
        """
        初始化报告生成器
        
        Args:
            config: 配置字典，包含生成器所需的各种配置参数
        """
        self.config = config
        self.logger = logging.getLogger(self.__class__.__name__)
    
    async def generate_report(self, request_data: Dict[str, Any]) -> ReportResult:
        """
        生成报告的主入口方法（模板方法）
        
        定义了报告生成的标准流程，子类通过实现抽象方法来定制具体行为。
        
        Args:
            request_data: 请求数据，包含生成报告所需的参数
            
        Returns:
            ReportResult: 报告生成结果
        """
        try:
            self.logger.info(f"开始生成报告: {self.__class__.__name__}")
            
            # 1. 数据提取阶段
            self.logger.info("步骤1: 数据提取")
            raw_data = await self.extract_data(request_data)
            
            # 2. 数据转换阶段
            self.logger.info("步骤2: 数据转换")
            processed_data = await self.transform_data(raw_data, request_data)
            
            # 3. AI分析阶段
            self.logger.info("步骤3: AI分析")
            ai_content = await self.analyze_with_ai(processed_data, request_data)
            
            # 4. 输出生成阶段
            self.logger.info("步骤4: 输出生成")
            result = await self.generate_output(ai_content, processed_data, request_data)
            
            self.logger.info("报告生成完成")
            return result
            
        except Exception as e:
            self.logger.error(f"报告生成失败: {str(e)}", exc_info=True)
            return ReportResult(
                success=False,
                error_message=f"报告生成失败: {str(e)}"
            )
    
    @abstractmethod
    async def extract_data(self, request_data: Dict[str, Any]) -> RawData:
        """
        数据提取阶段 - 子类必须实现
        
        从数据源（ES、MongoDB等）提取生成报告所需的原始数据。
        
        Args:
            request_data: 请求数据
            
        Returns:
            RawData: 提取的原始数据
        """
        pass
    
    @abstractmethod
    async def transform_data(self, raw_data: RawData, request_data: Dict[str, Any]) -> ProcessedData:
        """
        数据转换阶段 - 子类必须实现
        
        将原始数据转换为适合AI分析的格式，包括数据清洗、统计计算等。
        
        Args:
            raw_data: 原始数据
            request_data: 请求数据
            
        Returns:
            ProcessedData: 处理后的数据
        """
        pass
    
    @abstractmethod
    async def analyze_with_ai(self, processed_data: ProcessedData, request_data: Dict[str, Any]) -> str:
        """
        AI分析阶段 - 子类必须实现
        
        调用AI服务对处理后的数据进行分析，生成报告内容。
        
        Args:
            processed_data: 处理后的数据
            request_data: 请求数据
            
        Returns:
            str: AI生成的报告内容（HTML格式）
        """
        pass
    
    @abstractmethod
    async def generate_output(self, ai_content: str, processed_data: ProcessedData, 
                            request_data: Dict[str, Any]) -> ReportResult:
        """
        输出生成阶段 - 子类必须实现
        
        将AI生成的内容转换为最终的输出格式（PDF、URL等）。
        
        Args:
            ai_content: AI生成的内容
            processed_data: 处理后的数据
            request_data: 请求数据
            
        Returns:
            ReportResult: 最终的报告结果
        """
        pass
    
    def get_time_range(self, request_data: Dict[str, Any]) -> tuple[datetime, datetime, int]:
        """
        获取时间范围的通用方法
        
        Args:
            request_data: 请求数据
            
        Returns:
            tuple: (开始时间, 结束时间, 总天数)
        """
        from pytz import timezone
        
        start_date = request_data['startDate']
        end_date = request_data['endDate']
        
        # 计算总天数
        total_days = (datetime.strptime(end_date, '%Y-%m-%dT%H:%M:%S.%fZ')
                     - datetime.strptime(start_date, '%Y-%m-%dT%H:%M:%S.%fZ')).days + 1
        
        # 设置时区为北京时间
        beijing_tz = timezone('Asia/Shanghai')
        
        # 转换为datetime对象并设置时区
        start_time = datetime.strptime(start_date, '%Y-%m-%dT%H:%M:%S.%fZ').astimezone(beijing_tz)
        end_time = datetime.strptime(end_date, '%Y-%m-%dT%H:%M:%S.%fZ').astimezone(beijing_tz)
        
        return start_time, end_time, total_days
    
    def format_imei(self, df: pd.DataFrame, column: str = 'imei') -> pd.DataFrame:
        """
        格式化IMEI字段的通用方法
        
        Args:
            df: 数据框
            column: IMEI列名
            
        Returns:
            pd.DataFrame: 格式化后的数据框
        """
        if column in df.columns:
            df[column] = df[column].str[-6:]  # 取最后6位
        return df
    
    def df_to_csv_string(self, df: pd.DataFrame, separator: str = "|") -> str:
        """
        将DataFrame转换为CSV格式字符串
        
        Args:
            df: 数据框
            separator: 分隔符
            
        Returns:
            str: CSV格式字符串
        """
        return df.to_csv(index=False, encoding="utf-8", sep=separator)